<!--
 * @Date: 2024-10-25 15:02:59
 * @Author: LiSong
 * @LastEditors: g05047
 * @LastEditTime: 2025-01-20 15:06:31
 * @Description: 
-->
<template>
  <div v-if="treeShow"
    class="rk-aside-tree-wrapper">
    <div class="aside-tree-item"
      v-show="!insideAdTreeHidden">
      <div class="tree-item-search panel-header-graduabg-color"
        :style="{backgroundColor:(adBgc ? adBgc : '') + '!important'}">
        <template v-if="!adLabelHidden">
          <div class="item-search-title"
            :style=" adLabelWidth ? {
                width: adLabelWidth + 'px' 
            } : {}"
            :class="[
                      labelAlignArray.includes(adLabelAlign) ? adLabelAlign : '', 
                    ]">
            <span :style="{color:adLabelColor}">{{ adTitle }}</span>
          </div>
        </template>
        <div class="item-search-content">
          <el-input v-if="!adFilterable"
            v-model="adFilterText"
            :size="adSize"
            :placeholder="adPlaceholder"
            :prefix-icon="Search"
            clearable />
        </div>
      </div>
      <div class="tree-item-content"
        v-loading="adLoading">
        <div class="tree-item-content-center">
          <el-tree ref="adTreeRef"
            highlight-current
            :data="adTreeData"
            :props="adTreeProps"
            :node-key="adTreeProps.value"
            :filter-node-method="filterAdNodeMethod"
            :default-expand-all="adDefaultExpandAll"
            :default-expanded-keys="adDefaultExpandedKeys"
            @node-click="handleAdNodeClick"
            @current-change="handleAdNodeChange">
            <template #empty>
              <div class="no-data-container">
                <span class="no-data-text">暂无数据</span>
              </div>
            </template>
          </el-tree>
        </div>
      </div>
    </div>
    <div class="aside-tree-item"
      v-show="!insideAgTreeHidden">
      <div class="tree-item-search panel-header-graduabg-color"
        :style="{backgroundColor:(agBgc ? agBgc : '') + '!important' }">
        <template v-if="!agLabelHidden">
          <div class="item-search-title"
            :style=" agLabelWidth ? {
                width: agLabelWidth + 'px' 
            } : {}"
            :class="[
                      labelAlignArray.includes(agLabelAlign) ? agLabelAlign : '', 
                    ]">
            <span :style="{color:agLabelColor}">{{ agTitle }}</span>
          </div>
        </template>
        <div class="item-search-content">
          <el-input v-if="!agFilterable"
            v-model="agFilterText"
            :size="agSize"
            :placeholder="agPlaceholder"
            :prefix-icon="Search"
            clearable />
        </div>
      </div>
      <div class="tree-item-content"
        v-loading="agLoading">
        <div class="tree-item-content-center">
          <el-tree ref="agTreeRef"
            highlight-current
            :data="agTreeData"
            :props="agTreeProps"
            :node-key="adTreeProps.value"
            :filter-node-method="filterAgNodeMethod"
            :default-expand-all="agDefaultExpandAll"
            :default-expanded-keys="agDefaultExpandedKeys"
            @node-click="handleAgNodeClick"
            @current-change="handleAgNodeChange" >
            <template #empty>
              <div class="no-data-container">
                <span class="no-data-text">暂无数据</span>
              </div>
            </template>
          </el-tree>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup name="RkAdAgTreePanel">
import XEUtils from 'xe-utils';
import TreeUtils from '../cfg/tree-utils'

import { ElTree } from 'element-plus';
import { Search } from '@element-plus/icons-vue';
import { ref, computed, onBeforeMount, nextTick, watch, toRaw, inject, } from 'vue';

import { useTreeApi } from '@/api/api-tree';
import { adTreeDefaultProps, agTreeDefaultProps, agRootNode } from '../cfg/tree-config.js';

// 用户信息
const userInfo = computed(() => XEUtils.clone(props.userInfoData || {}, true));
// 组件中调用的APIxxx
const { getSysAdata, getSysAgData, getAdTree } = useTreeApi();

const axiosConfig = inject('axiosConfig')

// emits方法定义
const emits = defineEmits([
  'loaded',
  'adLoaded',
  'agLoaded',
  'nodeClick',
  'adNodeClick',
  'agNodeClick',
  'currentChange',
  'adCurrentChange',
  'agCurrentChange',
  'toggleHidden',
]);
const labelAlignArray = [
  'label-left-align',
  'label-center-align',
  'label-right-align'
]
// props
const props = defineProps({
  // ----- 公共属性
  // 宽度：默认100%
  width: { type: String, default: '100%' },
  // 高度：默认100%
  height: { type: String, default: '100%' },
  // 父节点是否可点击
  parentNodeClickable: { type: Boolean, default: false },
  // 当前登录人的数据
  userInfoData: {
    type: Object, default: () => { }
  },
  // 区划树唯一ID
  adId: { type: String | Number },
  // 区划背景色
  adBgc: { type: String, default: '' },
  // 区划标题色
  adLabelColor: { type: String, default: '' },
  // 区划树标题
  adTitle: { type: String, default: '区划' },
  // 区划标题隐藏
  adLabelHidden: { type: Boolean, default: false },
  // 区划大小
  adSize: { type: String },
  // 区划标题长度
  adLabelWidth: { type: String, },
  // 区划标题对齐
  adLabelAlign: {
    type: String, default: ''
  },
  // 区划树节点替换字段
  adTreeProps: {
    type: Object,
    default: () => {
      return adTreeDefaultProps;
    },
  },
  // 区划树是否隐藏：默认false
  adTreeHidden: { type: Boolean, default: false },
  // 区划搜索框提示语
  adPlaceholder: { type: String, default: '请输入关键词' },
  // 区划搜索是否隐藏：默认false
  adFilterable: { type: Boolean, default: false },
  // 区划树根节点是否可见
  adRootVisible: { type: Boolean, default: false },
  // 区划节点是否可重复点击
  adClickRepeatable: { type: Boolean, default: true },
  // 区划是否默认展开所有节点：默认false
  adDefaultExpandAll: { type: Boolean, default: false },
  // 区划节点点击是否自动展开
  adClickAutoExpanded: { type: Boolean, default: false },
  // 单位树唯一ID
  agId: { type: String | Number },
  // 单位树标题
  agTitle: { type: String, default: '单位' },
  // 单位背景色
  agBgc: { type: String, default: '' },
  // 单位标题色
  agLabelColor: { type: String, default: '' },
  // 单位标题隐藏
  agLabelHidden: { type: Boolean, default: false },
  // 单位大小
  agSize: { type: String },
  // 单位标题长度
  agLabelWidth: { type: String },
  // 单位标题对齐
  agLabelAlign: {
    type: String, default: ''
  },
  // 区划树节点替换字段
  agTreeProps: {
    type: Object,
    default: () => {
      return agTreeDefaultProps;
    },
  },
  // 单位树是否隐藏：默认false
  agTreeHidden: { type: Boolean, default: false },
  // 单位搜索框提示语
  agPlaceholder: { type: String, default: '请输入关键词' },
  // 单位搜索是否隐藏：默认false
  agFilterable: { type: Boolean, default: false },
  // 单位树根节点是否可见
  agRootVisible: { type: Boolean, default: false },
  // 单位节点是否可重复点击
  agClickRepeatable: { type: Boolean, default: true },
  // 单位是否默认展开所有节点：默认false
  agDefaultExpandAll: { type: Boolean, default: false },
  agClickAutoExpanded: { type: Boolean, default: false },
  isAdTree: { type: Boolean, default: false },
});
// 判断是否要重新加载
const treeShow = ref(true)
onBeforeMount(() => {
  loadTreeData();
});

// ----- 监听adTreeProps,agTreeProps 实现刷新
watch(() => [props.adTreeProps, props.agTreeProps], async ([v1, v2]) => {
  if (v1 && v2) {
    treeShow.value = false
    await nextTick()
    treeShow.value = true
  }
}, { deep: true, immediate: false })

// ----- 公共的emits操作
const emitLoaded = () => {
  emits('loaded', toRaw(adTreeData), toRaw(agTreeData));
};
const emitNodeClick = () => {
  emits('nodeClick', toRaw(adCurrentNode.value), toRaw(agCurrentNode.value));
};
const emitCurrentChange = () => {
  // 区划显示 单位显示 - 单位加载完以后触发
  emits('currentChange', toRaw(adCurrentNode.value), toRaw(agCurrentNode.value));
};
const emitToggleHidden = () => {
  emits('toggleHidden', insideAdTreeHidden.value && insideAgTreeHidden.value);
};

// 加载树结构数据
const loadTreeData = async () => {
  if (insideAdTreeHidden.value) {
    const { agId, adBjCode: adCode } = userInfo.value;
    await loadAgTreeData({ agId, adCode });
  } else {
    await loadAdTreeData();

  }
  emitToggleHidden();
};
// ----- 区划树结构操作
const adLoading = ref(false);
const adTreeRef = ref();
const adTreeData = ref([]);
const adFilterText = ref('');
const adCurrentNode = ref({});
const adOldCurrentNode = ref({});
const insideAdTreeHidden = ref(props.adTreeHidden)
//监听区划树隐藏
watch(() => props.adTreeHidden,
  (newData) => {
    insideAdTreeHidden.value = newData
    loadTreeData();
  },
  { deep: false, immediate: false }
)
const adDefaultExpandedKeys = ref([]);
// 加载区划树
const loadAdTreeData = async () => {
  if (insideAdTreeHidden.value) return;
  const treeData = await getAdTreeData();
  initAdTreeData(treeData);
  initAdTreeHidden(treeData);
  initAdTreeConfig(treeData);
  initAdTreeLoaded(treeData);
  if (insideAgTreeHidden.value) {
    emitLoaded();
  }
};
const reloadAdTreeData = async () => {
  const treeData = await getAdTreeData();
  initAdTreeData(treeData);
  initAdTreeHidden(treeData);
  initAdTreeConfig(treeData);
  initAdTreeLoaded(treeData);
  // 设置选中
  if (adCurrentNode.value[props.adTreeProps.value]) {
    nextTick(() => {
      adTreeRef?.value.setCurrentKey(adCurrentNode.value[props.adTreeProps.value]);
    });
  }
};
// 初始化区划树结构
const initAdTreeData = (treeData) => {
  adTreeData.value = treeData;
};
// 初始化区划树显示隐藏
const initAdTreeHidden = (treeData) => {
  // 是否只有一个节点，设置区划树隐藏显示
  const hidden = TreeUtils.hasOnlyOneNode(treeData);
  insideAdTreeHidden.value = hidden;

  // 如果区划树只有一个节点，并单位树不隐藏，将单位树隐藏
  if (hidden && !insideAgTreeHidden.value) {
    const { agId, adBjCode: adCode } = userInfo.value;
    loadAgTreeData({ agId, adCode })
  }
};
// 初始化区划树一些配置信息
const initAdTreeConfig = (treeData) => {
  const { adTreeProps } = props
  if (treeData && treeData.length > 0) {
    const treeNode = treeData[0];
    const treeNodeValue = treeNode[adTreeProps.value]
    const treeNodeChildren = treeNode[adTreeProps.children] ?? []
    let expandedKeys = [treeNodeValue]
    let customExpandedKeys = treeNodeChildren.filter(item => item.childNum > 0).map(item => item[adTreeProps.value])

    if (customExpandedKeys.length === 1) {
      customExpandedKeys = [customExpandedKeys[0]]
    } else {
      customExpandedKeys = []
    }
    expandedKeys = [
      ...expandedKeys,
      ...customExpandedKeys
    ]
    adDefaultExpandedKeys.value = expandedKeys;
    nextTick(() => {
      if (adTreeRef.value) adTreeRef?.value.setCurrentKey(treeNodeValue);
    });
  }
}
// 初始化区划树加载后
const initAdTreeLoaded = (treeData) => {
  emitAdLoaded(treeData);
};
const getAdTreeExpandedKeys = () => {

}

// 过滤区划树节点的方法
const filterAdNodeMethod = (value, data) => {
  if (!value) return true;
  return data[props.adTreeProps.label].includes(value);
};
// 区划树节点点击触发
const handleAdNodeClick = (data, treeNode, treeVNode, event) => {
  if (!props.adClickAutoExpanded) {
    treeNode.expanded = !treeNode.expanded;
  }
  let oldValue = adOldCurrentNode.value;
  let newValue = data[props.adTreeProps.value];
  if (!props.adClickRepeatable) {
    if (newValue === oldValue) {
      return;
    } else {
      adOldCurrentNode.value = newValue
    }
  } else {
    adOldCurrentNode.value = newValue
  }
  emitAdNodeClick(toRaw(data), treeNode);
  emitNodeClick();
};
// 区划树当前选中节点变化时触发的事件
const handleAdNodeChange = (data, treeNode) => {
  adCurrentNode.value = XEUtils.clone(toRaw(data), true);
  emitAdCurrentChange(toRaw(data), treeNode);
  if (!insideAdTreeHidden.value && insideAgTreeHidden.value) {
    emitCurrentChange();
  }
  const agQueryParams = { agId: userInfo.value.agId, adCode: data.code };
  loadAgTreeData(agQueryParams);
};
// 获取区划树数据
const getAdTreeData = () => {
  adLoading.value = true;
  return new Promise((reslove) => {
    if (props.isAdTree) {
      const params = { code: userInfo.value.adCode };
      getAdTree(axiosConfig.request, params)
        .then((res) => {
          const { code, data, msg } = res;
          reslove(code === 200 ? data : []);
        })
        .catch((err) => {
          console.error(err);
          reslove([]);
        })
        .finally(() => {
          adLoading.value = false;
        });
    } else {
      getSysAdata(axiosConfig.request)
        .then((res) => {
          const { code, data, msg } = res;
          reslove(code === 200 ? data : []);
        })
        .catch((err) => {
          console.error(err);
          reslove([]);
        })
        .finally(() => {
          adLoading.value = false;
        });
    }
  });
};
// ----- adTree watch 操作
// 监听区划树搜索框数据变化
watch(adFilterText, (newValue) => {
  if (adTreeRef) adTreeRef.value.filter(newValue);
});
// ----- adTree emits 操作
const emitAdLoaded = (treeData) => {
  emits('adLoaded', treeData);
};
const emitAdNodeClick = (data, treeNode) => {
  emits('adNodeClick', data, treeNode);
};
const emitAdCurrentChange = (data, treeNode) => {
  emits('adCurrentChange', data, treeNode);
};
// ----- 单位树结构操作
const agLoading = ref(false);
const agTreeRef = ref();
const agTreeData = ref([]);
const agFilterText = ref('');
const agCurrentNode = ref({});
const agOldCurrentNode = ref({});
const insideAgTreeHidden = ref(props.agTreeHidden);
watch(() => props.agTreeHidden,
  (newData) => {
    insideAdTreeHidden.value = newData ? (!insideAdTreeHidden.value ? false : true) : (!insideAdTreeHidden.value && !newData ? false : true)
    insideAgTreeHidden.value = newData
    loadTreeData()
  },
  { deep: false, immediate: false }
)
const agDefaultExpandedKeys = ref([]);
// 加载单位树
const loadAgTreeData = async (params) => {
  if (insideAgTreeHidden.value) return;
  const treeData = await getAgTreeData(params);
  initAgTreeHidden(treeData);
  const dealTreeData = initAgTreeData(treeData);
  initAgTreeConfig(dealTreeData);
  initAgTreeLoaded(treeData);
  emitLoaded();
};
// 重新加载单位树
const reloadAgTreeData = async () => {
  const { agId, adBjCode } = userInfo.value;
  let adCode = adCurrentNode.value.code || adBjCode;
  const queryParams = { agId, adCode };
  const treeData = await getAgTreeData(queryParams);
  initAgTreeHidden(treeData);
  const dealTreeData = initAgTreeData(treeData);
  initAgTreeConfig(dealTreeData);
  initAgTreeLoaded(treeData);
  emitLoaded();
  const currentKey = agCurrentNode.value[agTreeProps.value];
  if (currentKey) {
    nextTick(() => {
      if (agTreeRef.value) {
        agTreeRef.value.setCurrentKey(currentKey);
      }
    });
  }
};
// 初始化单位树结构
const initAgTreeData = (treeData) => {
  let resultTreeData = [];
  // 处理树机构存在全部节点
  if (treeData && treeData.length > 2) {
    const rootNode = XEUtils.clone(agRootNode, true);
    rootNode.children = treeData;
    let newTreeData = [rootNode];
    agTreeData.value = newTreeData;
    resultTreeData = newTreeData;
  } else {
    agTreeData.value = treeData;
    resultTreeData = treeData;
  }
  return resultTreeData;
};
// 初始化单位树显示隐藏
const initAgTreeHidden = (treeData) => {
  const hidden = TreeUtils.hasOnlyOneNode(treeData);
  insideAgTreeHidden.value = hidden;
};
// 初始化单位树一些配置信息
const initAgTreeConfig = (treeData) => {
  if (treeData && treeData.length > 0) {
    const firstTreeNode = treeData[0];
    const firstTreeNodeValue = String(firstTreeNode[props.agTreeProps.value]);
    agDefaultExpandedKeys.value = [firstTreeNodeValue];
    nextTick(() => {
      if (agTreeRef.value) {
        agTreeRef.value.setCurrentKey(firstTreeNodeValue);
      }
    });
  } else {
    emitCurrentChange();
  }
};
// 初始化单位树加载后
const initAgTreeLoaded = (treeData) => {
  emitAgLoaded(treeData);
};
// 过滤单位树节点的方法
const filterAgNodeMethod = (value, data) => {
  if (!value) return true;
  return data[props.agTreeProps.label].includes(value);
};
// 单位树节点点击触发
const handleAgNodeClick = (data, treeNode, treeVNode, event) => {
  if (!props.agClickAutoExpanded) {
    treeNode.expanded = !treeNode.expanded;
  }
  let oldValue = agOldCurrentNode.value
  let newValue = data[props.agTreeProps.value];
  if (!props.agClickRepeatable) {
    if (newValue === oldValue) {
      return;
    } else {
      agOldCurrentNode.value = newValue
    }
  } else {
    agOldCurrentNode.value = newValue
  }
  emitAgNodeClick(toRaw(data), treeNode);
  emitNodeClick();
};
// 单位树当前选中节点变化时触发的事件
const handleAgNodeChange = (data, treeNode) => {
  agCurrentNode.value = XEUtils.clone(toRaw(data), true);
  emitAgCurrentChange(toRaw(data), treeNode);
  emitCurrentChange();
};
// 获取单位树数据
const getAgTreeData = (params) => {
  agLoading.value = true;
  return new Promise((reslove) => {
    getSysAgData(axiosConfig.request, params)
      .then((res) => {
        const { code, data, msg } = res;
        reslove(code === 200 ? data : []);
      })
      .catch((err) => {
        console.error(err);
        reslove([]);
      })
      .finally(() => {
        agLoading.value = false;
      });
  });
};
// ----- agTree watch 操作
// 监听区划树搜索框数据变化
watch(agFilterText, (newValue) => {
  if (agTreeRef.value) agTreeRef.value.filter(newValue);
});
// ----- agTree emits 操作
const emitAgLoaded = (treeData) => {
  emits('agLoaded', treeData);
};
const emitAgNodeClick = (data, treeNode) => {
  emits('agNodeClick', data, treeNode);
};
const emitAgCurrentChange = (data, treeNode) => {
  emits('agCurrentChange', data, treeNode);
};

defineExpose({
  reloadAdTreeData,
  reloadAgTreeData,
});
</script>

<style lang="scss" scoped>
@import "../style/pub-tree.scss";
</style>
